/*
* Open-Source tuning tools
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.vgi.mafscaling;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Stack;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Pattern;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.apache.log4j.Logger;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.StandardTickUnitSource;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.Marker;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.ValueMarker;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.TextAnchor;
import org.math.plot.Plot3DPanel;
import org.scijava.swing.checkboxtree.CheckBoxNodeData;
import org.scijava.swing.checkboxtree.CheckBoxNodeEditor;
import org.scijava.swing.checkboxtree.CheckBoxNodePanel;
import org.scijava.swing.checkboxtree.CheckBoxNodeRenderer;
import quick.dbtable.Column;
import quick.dbtable.DBTable;
import quick.dbtable.PrintProperties;
import quick.dbtable.Skin;
import quick.dbtable.Filter;
public class LogView extends FCTabbedPane implements ActionListener {
private static final long serialVersionUID = -3803091816206090707L;
private static final Logger logger = Logger.getLogger(LogView.class);
private static final int tableControlPanelNumComponents = 7;
private static final int tableRowTextFieldComponentIdx = 3;
private static final int tableRowTextFieldSize = 5;
private static final int iconWidthHeight = 20;
private static final int iconFillPadding1 = 4;
private static final int iconFillPadding2 = 5;
private static final int maxNumPlots = 5;
private static final Color chartColor = new Color(60, 60, 65);
private static final Color chartBgColor = new Color(80, 80, 85);
private static final String prototypeDisplayValue = "XXXXXXXXXXXXXXXXXXXXXXXXXXX";
private static final String greater = ">";
private static final String greaterEqual = ">=";
private static final String less = "<";
private static final String lessEqual = "<=";
private static final String equal = "=";
private static final String rpmAxisName = "Engine Speed (RPM)";
private static final String timeAxisName = "Time (RPM aligned)";
private static final String fileNameReplaceString = "\\<.*?\\>";
private static final String pullIndexReplaceString = "Pull ";
private static final String rpmMatchString = ".*rpm.*";
private static final String engineSpeedMatchString = ".*eng.*speed.*";
private static final String timeMatchString = "^\\s*time\\s*(\\(.*\\))?$";
public class XYZ {
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
long temp;
temp = Double.doubleToLongBits(x);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(y);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(z);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
XYZ other = (XYZ) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x))
return false;
if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y))
return false;
if (Double.doubleToLongBits(z) != Double.doubleToLongBits(other.z))
return false;
return true;
}
private double x;
private double y;
private double z;
XYZ(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
private LogView getOuterType() {
return LogView.this;
}
}
public class TableSkin extends Skin {
private static final long serialVersionUID = 8263328522848779295L;
Font headerFont = new Font("Arial", Font.PLAIN, 12);
Font font = new Font("Arial", Font.PLAIN, 11);
@SuppressWarnings("unchecked")
public TableSkin() {
put(Skin.HEADER_FONT,headerFont);
put(Skin.TABLE_FONT,font);
put(Skin.ROW_HEIGTH, new Integer(16));
put(Skin.FOCUS_CELL_HIGHLIGHT_BORDER,new javax.swing.border.MatteBorder(2, 2, 2, 2, Color.BLACK));
}
}
public class SortingPopUp extends JPopupMenu implements ActionListener {
private static final long serialVersionUID = -8399244173709551368L;
JMenuItem sortAscending;
JMenuItem sortDescending;
int columnIndex;
public SortingPopUp(int column) {
columnIndex = column;
sortAscending = new JMenuItem("Sort Ascending");
sortAscending.setActionCommand("sortascending");
sortAscending.addActionListener(this);
add(sortAscending);
sortDescending = new JMenuItem("Sort Descending");
sortDescending.setActionCommand("sortdescending");
sortDescending.addActionListener(this);
add(sortDescending);
}
@Override
public void actionPerformed(ActionEvent e) {
if ("sortascending".equals(e.getActionCommand()))
sortAscending(columnIndex);
else if ("sortdescending".equals(e.getActionCommand()))
sortDescending(columnIndex);
}
}
public class DoubleComparator implements quick.dbtable.Comparator {
public int compare(int column, Object currentData, Object nextData) {
Double v1 = Double.valueOf(currentData.toString());
Double v2 = Double.valueOf(nextData.toString());
return Double.compare(v1, v2);
}
}
public static class CompareFilter implements Filter {
public enum Condition {
NONE,
GREATER,
GREATER_EQUAL,
EQUAL,
LESS_EQUAL,
LESS
}
private int colId = 0;
private Condition condition = Condition.NONE;
private String filterString = "0";
private double filter = Double.NaN;
public void setColumn(int id) {
colId = id;
}
public void setCondition(Condition c) {
condition = c;
}
public void setFilter(String f) {
filterString = f;
filter = Double.valueOf(filterString);
}
public int[] filter(TableModel tm) {
if (Double.isNaN(filter) || Condition.NONE == condition)
return new int[0];
ArrayList<Integer> list = new ArrayList<Integer>();
double value;
int rounding = 0;
int i = 0;
if (filterString.indexOf('.') != -1) {
filterString = filterString.substring(filterString.indexOf('.'));
rounding = filterString.length() - 1;
}
for (i = 0; i < tm.getRowCount(); ++i) {
try {
value = Double.valueOf((String)tm.getValueAt(i, colId));
}
catch (Exception e) {
continue;
}
switch (condition) {
case LESS:
if (value < filter)
list.add(i);
break;
case LESS_EQUAL:
if (value <= filter)
list.add(i);
break;
case GREATER_EQUAL:
if (value >= filter)
list.add(i);
break;
case GREATER:
if (value > filter)
list.add(i);
break;
default:
double rndVal = value;
if (rounding > 0) {
double multiplier = Math.pow(10.0, rounding);
rndVal = Math.round(value * multiplier) / multiplier;
}
else
rndVal = Math.round(value);
if (Utils.equals(rndVal, filter))
list.add(i);
break;
}
}
int arr[] = new int[list.size()];
for (i = 0; i < list.size(); ++i)
arr[i] = list.get(i);
return arr;
}
}
public class FileNodeRenderer extends CheckBoxNodeRenderer {
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
Component renderer = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
renderer.setBackground(null);
DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
if (renderer instanceof DefaultTreeCellRenderer && node.getAllowsChildren()) {
((DefaultTreeCellRenderer)renderer).setIcon(null);
((DefaultTreeCellRenderer)renderer).setOpaque(false);
((DefaultTreeCellRenderer)renderer).setBackgroundNonSelectionColor(null);
}
else {
CheckBoxNodePanel panel = (CheckBoxNodePanel)renderer;
if (!panel.hasFocus() && selected)
wotTree.clearSelection();
}
return renderer;
}
}
public class CheckBoxIcon implements Icon {
private Color color;
private boolean checked;
public CheckBoxIcon() { this.checked = false; this.color = UIManager.getColor("Panel.background"); }
public CheckBoxIcon(boolean checked, Color color) { this.checked = checked; this.color = color; }
public Color getColor() { return this.color; }
public void setColor(Color color) { this.color = color; }
public boolean isChecked() { return this.checked; }
public void setChecked(boolean checked) { this.checked = checked; }
@Override
public int getIconWidth() { return iconWidthHeight; }
@Override
public int getIconHeight() { return iconWidthHeight; }
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
g.setColor(Color.BLACK);
g.fillRect(x + iconFillPadding1, y + iconFillPadding1, getIconWidth() - iconFillPadding1 * 2, getIconHeight() - iconFillPadding1 * 2);
g.setColor(color);
g.fillRect(x + iconFillPadding2, y + iconFillPadding2, getIconWidth() - iconFillPadding2 * 2, getIconHeight() - iconFillPadding2 * 2);
}
}
public class CheckboxHeaderRenderer implements TableCellRenderer {
private final CheckBoxIcon checkIcon = new CheckBoxIcon();
private int colId = -1;
MouseListener mouseListener = null;
private Color defaultColor = checkIcon.getColor();
public CheckboxHeaderRenderer(int col, JTableHeader header) {
colId = col;
mouseListener = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
try {
JTable table = ((JTableHeader) e.getSource()).getTable();
TableColumnModel columnModel = table.getColumnModel();
int viewColumn = columnModel.getColumnIndexAtX(e.getX());
int modelColumn = table.convertColumnIndexToModel(viewColumn);
if (colId != modelColumn)
return;
if (SwingUtilities.isLeftMouseButton(e) && colors.size() > 0) {
checkIcon.setChecked(!checkIcon.isChecked());
if (checkIcon.isChecked()) {
defaultColor = checkIcon.getColor();
checkIcon.setColor(colors.pop());
TableModel model = table.getModel();
addXYSeries(model, colId - 1, columnModel.getColumn(viewColumn).getHeaderValue().toString(), checkIcon.getColor());
}
else {
colors.push(checkIcon.getColor());
checkIcon.setColor(defaultColor);
removeXYSeries(colId - 1);
}
((JTableHeader) e.getSource()).repaint();
}
else if (SwingUtilities.isRightMouseButton(e)) {
SortingPopUp menu = new SortingPopUp(colId);
menu.show(e.getComponent(), e.getX(), e.getY());
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
};
header.addMouseListener(mouseListener);
}
@Override
public Component getTableCellRendererComponent(JTable tbl, Object val, boolean isS, boolean hasF, int row, int col) {
TableCellRenderer r = tbl.getTableHeader().getDefaultRenderer();
JLabel label = (JLabel) r.getTableCellRendererComponent(tbl, val, isS, hasF, row, col);
label.setIcon(checkIcon);
return label;
}
public CheckBoxIcon getCheckIcon() { return checkIcon; }
public Color getDefaultColor() { return defaultColor; }
public MouseListener getMouseListener() { return mouseListener; }
}
class ImageListCellRenderer implements ListCellRenderer<Object> {
public Component getListCellRendererComponent(JList<?> jlist, Object value, int cellIndex, boolean isSelected, boolean cellHasFocus) {
if (value instanceof JLabel)
return (Component)value;
else
return new JLabel("???");
}
}
private ChartPanel chartPanel = null;
private ChartPanel wotChartPanel = null;
private JTree wotTree = null;
private XYPlot plot = null;
private XYPlot wotPlot = null;
private XYSeriesCollection rpmDataset = null;
private XYSeriesCollection dataset = null;
private XYLineAndShapeRenderer rpmPlotRenderer = null;
private XYLineAndShapeRenderer plotRenderer = null;
private int rpmCol = -1;
private int displCount = 0;
private JPanel logViewPanel = null;
private JToolBar toolBar = null;
private DBTable logDataTable = null;
private DBTFindFrame findWindow = null;
private LogPlay logPlayWindow = null;
private JScrollPane headerScrollPane = null;
private DefaultListModel<JLabel> listModel = null;
private JButton loadButton = null;
private JButton printButton = null;
private JButton previewButton = null;
private JButton findButton = null;
private JButton replaceButton = null;
private JComboBox<String> selectionCombo;
private JComboBox<String> compareCombo;
private JTextField filterText;
private JButton filterButton;
private JButton viewButton;
private JButton logPlayButton;
private Plot3DPanel plot3d = null;
private ChartMouseListener chartMouseListener = null;
private JComboBox<String> xAxisColumn = null;
private JComboBox<String> yAxisColumn = null;
private JMultiSelectionBox plotsColumn = null;
private JMultiSelectionBox wotPlotsColumn = null;
private ButtonGroup wotRbGroup = null;
private HashMap<String, ArrayList<HashMap<String, ArrayList<Double>>>> filesData = null;
private int wotPoint = Config.getWOTStationaryPointValue();
private int logThtlAngleColIdx = -1;
private String logRpmColName = null;
private String logTimeColName = null;
private File lastPullExportDir = null;
private ValueMarker startMarker = null;
private ValueMarker endMarker = null;
private XYDomainMutilineAnnotation xMarker = null;
private XYDomainMutilineAnnotation wotMarker = null;
private Stack<Color> colors = new Stack<Color>();
private Insets insets0 = new Insets(0, 0, 0, 0);
private Insets insets3 = new Insets(3, 3, 3, 3);
private Insets insets10 = new Insets(10, 10, 10, 10);
private DecimalFormat df = new DecimalFormat("#.####");
private boolean showWotCurvePoints = false;
public LogView(int tabPlacement) {
super(tabPlacement);
initialize();
}
private void initialize() {
createDataTab();
createChartTab();
createWotChartTab();
createUsageTab();
}
public DBTable getLogDataTable() {
return logDataTable;
}
//////////////////////////////////////////////////////////////////////////////////////
// DATA TAB
//////////////////////////////////////////////////////////////////////////////////////
private void createDataTab() {
JPanel dataPanel = new JPanel(new BorderLayout());
add(dataPanel, "<html><div style='text-align: center;'>D<br>a<br>t<br>a</div></html>");
createToolBar(dataPanel);
createLogViewPanel();
createGraghPanel();
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, logViewPanel, chartPanel);
splitPane.setResizeWeight(0.5);
splitPane.setOneTouchExpandable(true);
splitPane.setContinuousLayout(true);
splitPane.setDividerLocation(150);
dataPanel.add(splitPane);
}
private void createLogViewPanel() {
logViewPanel = new JPanel();
GridBagLayout gbl_logViewPanel = new GridBagLayout();
gbl_logViewPanel.columnWidths = new int[] {0};
gbl_logViewPanel.rowHeights = new int[] {0, 0};
gbl_logViewPanel.columnWeights = new double[]{1.0};
gbl_logViewPanel.rowWeights = new double[]{1.0, 0.0};
logViewPanel.setLayout(gbl_logViewPanel);
try {
logDataTable = new DBTable();
logDataTable.copyColumnHeaderNames = true;
logDataTable.defaultClickCountToStartEditor = 2;
logDataTable.doNotUseDatabaseSort = true;
logDataTable.listenKeyPressEventsWholeWindow = true;
logDataTable.createControlPanel(DBTable.READ_NAVIGATION);
logDataTable.enableExcelCopyPaste();
logDataTable.setSortEnabled(false);
logDataTable.setSkin(new TableSkin());
logDataTable.refresh(new String[1][25]);
logDataTable.setComparator(new DoubleComparator());
logDataTable.getTable().setCellSelectionEnabled(true);
logDataTable.getTable().setColumnSelectionAllowed(true);
logDataTable.getTable().setRowSelectionAllowed(true);
logDataTable.getTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JTextField rowTextField = ((JTextField)logDataTable.getControlPanel().getComponent(tableRowTextFieldComponentIdx));
rowTextField.setPreferredSize(null);
rowTextField.setColumns(tableRowTextFieldSize);
GridBagConstraints gbc_logDataTable = new GridBagConstraints();
gbc_logDataTable.insets = insets0;
gbc_logDataTable.anchor = GridBagConstraints.PAGE_START;
gbc_logDataTable.fill = GridBagConstraints.BOTH;
gbc_logDataTable.gridx = 0;
gbc_logDataTable.gridy = 0;
logViewPanel.add(logDataTable, gbc_logDataTable);
listModel = new DefaultListModel<JLabel>();
selectionCombo.removeAllItems();
TreeSet<String> sortedCols = new TreeSet<String>();
JTableHeader tableHeader = logDataTable.getTableHeader();
for (int i = 0; i < logDataTable.getColumnCount(); ++i) {
Column col = logDataTable.getColumn(i);
col.setNullable(true);
col.setHeaderRenderer(new CheckboxHeaderRenderer(i + 1, tableHeader));
sortedCols.add(col.getHeaderValue().toString());
}
for (String s : sortedCols) {
selectionCombo.addItem(s);
listModel.addElement(new JLabel(s, new CheckBoxIcon(), JLabel.LEFT));
}
JList<JLabel> menuList = new JList<JLabel>(listModel);
menuList.setOpaque(false);
menuList.setCellRenderer(new ImageListCellRenderer());
menuList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
menuList.setLayoutOrientation(JList.VERTICAL_WRAP);
menuList.setFixedCellHeight(25);
menuList.setVisibleRowCount(-1);
menuList.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
try {
if (e.getClickCount() == 1 && colors.size() > 0) {
JList<?> list = (JList<?>)e.getSource();
int index = list.locationToIndex(e.getPoint());
if (index >= 0) {
JLabel label = (JLabel)list.getModel().getElementAt(index);
Column col = logDataTable.getColumnByHeaderName(label.getText());
if (col.getHeaderRenderer() instanceof CheckboxHeaderRenderer) {
CheckboxHeaderRenderer renderer = (CheckboxHeaderRenderer)col.getHeaderRenderer();
CheckBoxIcon checkIcon = (CheckBoxIcon)label.getIcon();
checkIcon.setChecked(!checkIcon.isChecked());
if (checkIcon.isChecked()) {
checkIcon.setColor(colors.pop());
JTable table = logDataTable.getTable();
TableModel model = table.getModel();
addXYSeries(model, col.getModelIndex() - 1, col.getHeaderValue().toString(), checkIcon.getColor());
}
else {
colors.push(checkIcon.getColor());
checkIcon.setColor(renderer.getDefaultColor());
removeXYSeries(col.getModelIndex() - 1);
}
list.repaint();
}
}
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
});
headerScrollPane = new JScrollPane(menuList);
GridBagConstraints gbc_headersTree = new GridBagConstraints();
gbc_headersTree.insets = insets0;
gbc_headersTree.anchor = GridBagConstraints.PAGE_START;
gbc_headersTree.fill = GridBagConstraints.BOTH;
gbc_headersTree.gridx = 0;
gbc_headersTree.gridy = 1;
logViewPanel.add(headerScrollPane, gbc_headersTree);
headerScrollPane.setVisible(false);
}
catch (Exception e) {
e.printStackTrace();
logger.error(e);
}
}
private void createToolBar(JPanel panel)
{
toolBar = new JToolBar();
panel.add(toolBar, BorderLayout.NORTH);
loadButton = addToolbarButton("Load Log File", "/open.png");
toolBar.addSeparator();
printButton = addToolbarButton("Print", "/print.png");
previewButton = addToolbarButton("Print Preview", "/print_preview.png");
findButton = addToolbarButton("Find", "/find.png");
replaceButton = addToolbarButton("Replace", "/replace.png");
toolBar.addSeparator();
viewButton = new JButton("Headers View");
viewButton.setMargin(new Insets(2, 7, 2, 7));
viewButton.addActionListener(this);
toolBar.add(viewButton);
toolBar.addSeparator();
logPlayButton = new JButton("Log Play");
logPlayButton.setMargin(new Insets(2, 7, 2, 7));
logPlayButton.addActionListener(this);
toolBar.add(logPlayButton);
toolBar.addSeparator();
toolBar.add(new JLabel("Filter "));
JPanel filterPanel = new JPanel();
GridBagLayout gbl_filterPanel = new GridBagLayout();
gbl_filterPanel.columnWidths = new int[]{0, 0, 0, 0};
gbl_filterPanel.rowHeights = new int[]{0};
gbl_filterPanel.columnWeights = new double[]{0.0, 0.0, 0.0, 1.0};
gbl_filterPanel.rowWeights = new double[]{0.0};
filterPanel.setLayout(gbl_filterPanel);
GridBagConstraints gbc_filter = new GridBagConstraints();
gbc_filter.insets = insets3;
gbc_filter.anchor = GridBagConstraints.WEST;
gbc_filter.gridx = 0;
gbc_filter.gridy = 0;
selectionCombo = new JComboBox<String>();
selectionCombo.setPrototypeDisplayValue(prototypeDisplayValue);
selectionCombo.addActionListener(this);
filterPanel.add(selectionCombo, gbc_filter);
gbc_filter.gridx++;
compareCombo = new JComboBox<String>(new String[] {"", less, lessEqual, equal, greaterEqual, greater});
compareCombo.addActionListener(this);
filterPanel.add(compareCombo, gbc_filter);
gbc_filter.gridx++;
filterText = new JTextField();
filterText.setColumns(5);
filterPanel.add(filterText, gbc_filter);
gbc_filter.gridx++;
filterButton = new JButton("Set");
filterButton.addActionListener(this);
filterPanel.add(filterButton, gbc_filter);
toolBar.add(filterPanel);
}
private void createGraghPanel() {
JFreeChart chart = ChartFactory.createXYLineChart(null, null, null, null, PlotOrientation.VERTICAL, false, true, false);
chartPanel = new ChartPanel(chart, true, true, true, true, true);
chartPanel.setFocusable(true);
chartPanel.setAutoscrolls(true);
chartPanel.setPopupMenu(null);
chart.setBackgroundPaint(chartColor);
rpmDataset = new XYSeriesCollection();
rpmPlotRenderer = new XYLineAndShapeRenderer();
dataset = new XYSeriesCollection();
plotRenderer = new XYLineAndShapeRenderer();
NumberAxis xAxis = new NumberAxis();
xAxis.setTickLabelsVisible(false);
xAxis.setTickLabelPaint(Color.WHITE);
xAxis.setAutoRangeIncludesZero(false);
NumberAxis yAxis = new NumberAxis();
yAxis.setTickLabelsVisible(false);
yAxis.setTickLabelPaint(Color.WHITE);
yAxis.setAutoRangeIncludesZero(false);
NumberAxis y2Axis = new NumberAxis();
y2Axis.setTickLabelsVisible(false);
y2Axis.setTickLabelPaint(Color.WHITE);
y2Axis.setAutoRangeIncludesZero(false);
plot = chartPanel.getChart().getXYPlot();
plot.setRangePannable(true);
plot.setDomainPannable(true);
plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
plot.setBackgroundPaint(chartBgColor);
plot.setDataset(0, rpmDataset);
plot.setRenderer(0, rpmPlotRenderer);
plot.setDomainAxis(0, xAxis);
plot.setRangeAxis(0, yAxis);
plot.mapDatasetToDomainAxis(0, 0);
plot.mapDatasetToRangeAxis(0, 0);
plot.setDataset(1, dataset);
plot.setRenderer(1, plotRenderer);
plot.setRangeAxis(1, y2Axis);
plot.mapDatasetToDomainAxis(1, 0);
plot.mapDatasetToRangeAxis(1, 1);
LegendTitle legend = new LegendTitle(plot);
legend.setItemFont(new Font("Arial", 0, 10));
legend.setPosition(RectangleEdge.TOP);
legend.setItemPaint(Color.WHITE);
chart.addLegend(legend);
xMarker = new XYDomainMutilineAnnotation();
plot.addAnnotation(xMarker);
chartMouseListener = new ChartMouseListener() {
@Override
public void chartMouseMoved(ChartMouseEvent event) {
try {
Rectangle2D dataArea = chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea();
Point2D p = chartPanel.translateScreenToJava2D(event.getTrigger().getPoint());
double x = plot.getDomainAxis().java2DToValue(p.getX(), dataArea, plot.getDomainAxisEdge());
boolean isLeft = (p.getX() < (dataArea.getMaxX() - dataArea.getMinX()) / 2) ? true : false;
if (setMarkers(x, isLeft)) {
try {
int selectedCol = logDataTable.getTable().getSelectedColumn();
if (selectedCol < 0)
selectedCol = 0;
if (logPlayWindow == null || startMarker != null || endMarker != null) {
logDataTable.getTable().setRowSelectionInterval((int)x, (int)x);
logDataTable.getTable().changeSelection((int)x, selectedCol, false, false);
}
else {
logPlayWindow.setProgressBar((int)x);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void chartMouseClicked(ChartMouseEvent event) {
chartPanel.requestFocusInWindow();
if (logPlayWindow == null)
return;
if (xMarker.count() == 0)
return;
Rectangle2D dataArea = chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea();
Point2D p = chartPanel.translateScreenToJava2D(event.getTrigger().getPoint());
double x = plot.getDomainAxis().java2DToValue(p.getX(), dataArea, plot.getDomainAxisEdge());
if (x < 0 || (int)x >= logDataTable.getRowCount())
return;
if (SwingUtilities.isLeftMouseButton(event.getTrigger())) {
if (startMarker == null) {
startMarker = new ValueMarker(x);
startMarker.setPaint(Color.GREEN);
startMarker.setStroke(new BasicStroke(1.5f));
plot.addDomainMarker(startMarker);
}
else {
plot.removeDomainMarker(startMarker);
startMarker = null;
}
}
else if (SwingUtilities.isRightMouseButton(event.getTrigger())) {
if (endMarker == null) {
endMarker = new ValueMarker(x);
endMarker.setPaint(Color.GREEN);
endMarker.setStroke(new BasicStroke(1.5f));
plot.addDomainMarker(endMarker);
}
else {
plot.removeDomainMarker(endMarker);
endMarker = null;
}
}
chartPanel.repaint();
logPlayWindow.setStartEndArea(startMarker, endMarker);
}
};
chartPanel.addChartMouseListener(chartMouseListener);
chartPanel.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
if (!chartPanel.hasFocus())
return;
int keyCode = e.getKeyCode();
if (keyCode < KeyEvent.VK_LEFT || keyCode > KeyEvent.VK_DOWN)
return;
ValueAxis axis = null;
if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT)
axis = ((XYPlot)chartPanel.getChart().getXYPlot()).getDomainAxis();
else
axis = ((XYPlot)chartPanel.getChart().getXYPlot()).getRangeAxis();
if (axis != null) {
double delta = (axis.getUpperBound()- axis.getLowerBound()) / 100.0;
if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_DOWN)
axis.setRange(axis.getLowerBound()- delta, axis.getUpperBound() - delta);
else if (keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_RIGHT)
axis.setRange(axis.getLowerBound() + delta, axis.getUpperBound() + delta);
}
}
public void keyReleased(KeyEvent arg0) { }
public void keyTyped(KeyEvent arg0) { }
});
}
//////////////////////////////////////////////////////////////////////////////////////
// CREATE 3D CHART TAB
//////////////////////////////////////////////////////////////////////////////////////
private void createChartTab() {
JPanel plotPanel = new JPanel();
add(plotPanel, "<html><div style='text-align: center;'>3<br>D<br><br>C<br>h<br>a<br>r<br>t</div></html>");
GridBagLayout gbl_plotPanel = new GridBagLayout();
gbl_plotPanel.columnWidths = new int[] {0};
gbl_plotPanel.rowHeights = new int[] {0, 0};
gbl_plotPanel.columnWeights = new double[]{1.0};
gbl_plotPanel.rowWeights = new double[]{0.0, 1.0};
plotPanel.setLayout(gbl_plotPanel);
JPanel cntlPanel = new JPanel();
GridBagConstraints gbc_ctrlPanel = new GridBagConstraints();
gbc_ctrlPanel.insets = insets3;
gbc_ctrlPanel.anchor = GridBagConstraints.NORTH;
gbc_ctrlPanel.weightx = 1.0;
gbc_ctrlPanel.fill = GridBagConstraints.HORIZONTAL;
gbc_ctrlPanel.gridx = 0;
gbc_ctrlPanel.gridy = 0;
plotPanel.add(cntlPanel, gbc_ctrlPanel);
GridBagLayout gbl_cntlPanel = new GridBagLayout();
gbl_cntlPanel.columnWidths = new int[]{0, 0, 0, 0, 0, 0, 0, 0};
gbl_cntlPanel.rowHeights = new int[]{0};
gbl_cntlPanel.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0};
gbl_cntlPanel.rowWeights = new double[]{0};
cntlPanel.setLayout(gbl_cntlPanel);
GridBagConstraints gbc_label = new GridBagConstraints();
gbc_label.anchor = GridBagConstraints.EAST;
gbc_label.insets = new Insets(3, 3, 3, 0);
gbc_label.gridx = 0;
gbc_label.gridy = 0;
GridBagConstraints gbc_column = new GridBagConstraints();
gbc_column.anchor = GridBagConstraints.WEST;
gbc_column.insets = insets3;
gbc_column.gridx = 1;
gbc_column.gridy = 0;
cntlPanel.add(new JLabel("X-Axis"), gbc_label);
xAxisColumn = new JComboBox<String>();
xAxisColumn.setPrototypeDisplayValue(prototypeDisplayValue);
cntlPanel.add(xAxisColumn, gbc_column);
gbc_label.gridx += 2;
cntlPanel.add(new JLabel("Y-Axis"), gbc_label);
gbc_column.gridx += 2;
yAxisColumn = new JComboBox<String>();
yAxisColumn.setPrototypeDisplayValue(prototypeDisplayValue);
cntlPanel.add(yAxisColumn, gbc_column);
gbc_label.gridx += 2;
cntlPanel.add(new JLabel("Plots"), gbc_label);
gbc_column.gridx += 2;
plotsColumn = new JMultiSelectionBox();
plotsColumn.setPrototypeDisplayValue(prototypeDisplayValue);
cntlPanel.add(plotsColumn, gbc_column);
gbc_label.gridx += 2;
JButton btnGoButton = new JButton("View");
btnGoButton.setActionCommand("view");
btnGoButton.addActionListener(this);
cntlPanel.add(btnGoButton, gbc_label);
plot3d = new Plot3DPanel("SOUTH") {
private static final long serialVersionUID = 7914951068593204419L;
public void addPlotToolBar(String location) {
super.addPlotToolBar(location);
super.plotToolBar.remove(7);
super.plotToolBar.remove(5);
super.plotToolBar.remove(4);
}
};
plot3d.setAutoBounds();
plot3d.setAutoscrolls(true);
plot3d.setEditable(false);
plot3d.setBorder(BorderFactory.createLineBorder(Color.BLACK));
plot3d.setForeground(Color.BLACK);
plot3d.getAxis(0).setColor(Color.BLACK);
plot3d.getAxis(1).setColor(Color.BLACK);
plot3d.getAxis(2).setColor(Color.BLACK);
GridBagConstraints gbc_chartPanel = new GridBagConstraints();
gbc_chartPanel.anchor = GridBagConstraints.CENTER;
gbc_chartPanel.insets = insets3;
gbc_chartPanel.weightx = 1.0;
gbc_chartPanel.weighty = 1.0;
gbc_chartPanel.fill = GridBagConstraints.BOTH;
gbc_chartPanel.gridx = 0;
gbc_chartPanel.gridy = 1;
plotPanel.add(plot3d, gbc_chartPanel);
}
//////////////////////////////////////////////////////////////////////////////////////
// CREATE WOT TAB
//////////////////////////////////////////////////////////////////////////////////////
private void createWotChartTab() {
JPanel plotPanel = new JPanel();
add(plotPanel, "<html><div style='text-align: center;'>W<br>O<br>T<br><br>P<br>u<br>l<br>l<br>s</div></html>");
GridBagLayout gbl_plotPanel = new GridBagLayout();
gbl_plotPanel.columnWidths = new int[] {0};
gbl_plotPanel.rowHeights = new int[] {0, 0};
gbl_plotPanel.columnWeights = new double[]{1.0};
gbl_plotPanel.rowWeights = new double[]{0.0, 1.0};
plotPanel.setLayout(gbl_plotPanel);
createWotCtrlPanel(plotPanel);
createWotTreePanel();
createWotChart();
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(wotTree), wotChartPanel);
splitPane.setResizeWeight(0.5);
splitPane.setOneTouchExpandable(true);
splitPane.setContinuousLayout(true);
splitPane.setDividerLocation(150);
GridBagConstraints gbc_dataPanel = new GridBagConstraints();
gbc_dataPanel.insets = insets3;
gbc_dataPanel.anchor = GridBagConstraints.CENTER;
gbc_dataPanel.weightx = 1.0;
gbc_dataPanel.weighty = 1.0;
gbc_dataPanel.fill = GridBagConstraints.BOTH;
gbc_dataPanel.gridx = 0;
gbc_dataPanel.gridy = 1;
plotPanel.add(splitPane, gbc_dataPanel);
}
protected void createWotCtrlPanel(JPanel plotPanel) {
wotRbGroup = new ButtonGroup();
JPanel cntlPanel = new JPanel();
GridBagConstraints gbc_ctrlPanel = new GridBagConstraints();
gbc_ctrlPanel.insets = insets3;
gbc_ctrlPanel.anchor = GridBagConstraints.NORTH;
gbc_ctrlPanel.weightx = 1.0;
gbc_ctrlPanel.fill = GridBagConstraints.HORIZONTAL;
gbc_ctrlPanel.gridx = 0;
gbc_ctrlPanel.gridy = 0;
plotPanel.add(cntlPanel, gbc_ctrlPanel);
GridBagLayout gbl_cntlPanel = new GridBagLayout();
gbl_cntlPanel.columnWidths = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0};
gbl_cntlPanel.rowHeights = new int[]{0};
gbl_cntlPanel.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0};
gbl_cntlPanel.rowWeights = new double[]{0};
cntlPanel.setLayout(gbl_cntlPanel);
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = insets3;
gbc.gridx = 0;
gbc.gridy = 0;
JButton btnAddButton = new JButton("Load Log");
btnAddButton.setActionCommand("loadWot");
btnAddButton.addActionListener(this);
cntlPanel.add(btnAddButton, gbc);
gbc.gridx += 1;
gbc.anchor = GridBagConstraints.EAST;
cntlPanel.add(new JLabel("Plots"), gbc);
gbc.gridx += 1;
gbc.anchor = GridBagConstraints.WEST;
wotPlotsColumn = new JMultiSelectionBox();
wotPlotsColumn.setPrototypeDisplayValue(prototypeDisplayValue);
cntlPanel.add(wotPlotsColumn, gbc);
gbc.gridx += 1;
JRadioButton button = new JRadioButton("RPM");
wotRbGroup.add(button);
cntlPanel.add(button, gbc);
gbc.gridx += 1;
button = new JRadioButton("RPM (skip down spikes)");
wotRbGroup.add(button);
cntlPanel.add(button, gbc);
gbc.gridx += 1;
button = new JRadioButton(timeAxisName);
wotRbGroup.add(button);
cntlPanel.add(button, gbc);
gbc.gridx += 1;
JCheckBox checkBox = new JCheckBox("Show points");
checkBox.setActionCommand("showpts");
checkBox.addActionListener(this);
cntlPanel.add(checkBox, gbc);
gbc.gridx += 1;
JButton exportButton = new JButton("Export Selected Pulls");
exportButton.setActionCommand("export");
exportButton.addActionListener(this);
cntlPanel.add(exportButton, gbc);
gbc.gridx += 1;
gbc.anchor = GridBagConstraints.EAST;
JButton btnGoButton = new JButton("View");
btnGoButton.setActionCommand("viewWot");
btnGoButton.addActionListener(this);
cntlPanel.add(btnGoButton, gbc);
((JRadioButton)wotRbGroup.getElements().nextElement()).setSelected(true);
}
protected void createWotTreePanel() {
DefaultMutableTreeNode wotTreeRoot = new DefaultMutableTreeNode("Root");
DefaultTreeModel treeModel = new DefaultTreeModel(wotTreeRoot);
wotTree = new JTree(treeModel);
wotTree.setCellRenderer(new FileNodeRenderer());
wotTree.setCellEditor(new CheckBoxNodeEditor(wotTree));
wotTree.setEditable(true);
wotTree.setRootVisible(false);
wotTree.setOpaque(false);
wotTree.setBackground(null);
wotTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
}
protected void createWotChart() {
wotMarker = new XYDomainMutilineAnnotation();
JFreeChart chart = ChartFactory.createXYLineChart(null, null, null, null, PlotOrientation.VERTICAL, false, true, false);
wotChartPanel = new ChartPanel(chart, true, true, true, true, true);
wotChartPanel.setFocusable(true);
wotChartPanel.setAutoscrolls(true);
chart.setBackgroundPaint(chartColor);
wotPlot = chart.getXYPlot();
wotPlot.setRangePannable(true);
wotPlot.setDomainPannable(true);
wotPlot.setDomainGridlinePaint(Color.LIGHT_GRAY);
wotPlot.setRangeGridlinePaint(Color.LIGHT_GRAY);
wotPlot.setBackgroundPaint(chartBgColor);
wotPlot.addAnnotation(wotMarker);
wotPlot.setRangeAxis(null);
NumberAxis xAxis = new NumberAxis();
xAxis.setAutoRangeIncludesZero(false);
xAxis.setTickLabelPaint(Color.WHITE);
xAxis.setLabelPaint(Color.LIGHT_GRAY);
wotPlot.setDomainAxis(0, xAxis);
wotPlot.setDataset(0, new XYSeriesCollection());
wotPlot.mapDatasetToDomainAxis(0, 0);
wotPlot.mapDatasetToRangeAxis(0, 0);
LegendTitle legend = new LegendTitle(wotPlot);
legend.setItemFont(new Font("Arial", 0, 10));
legend.setPosition(RectangleEdge.TOP);
legend.setItemPaint(Color.WHITE);
chart.addLegend(legend);
wotChartPanel.addChartMouseListener(new ChartMouseListener() {
@Override
public void chartMouseMoved(ChartMouseEvent event) {
try {
wotPlot.clearRangeMarkers();
wotMarker.clearLabels(false);
Rectangle2D dataArea = wotChartPanel.getChartRenderingInfo().getPlotInfo().getDataArea();
Point2D p = wotChartPanel.translateScreenToJava2D(event.getTrigger().getPoint());
double y = 0;
double x = wotPlot.getDomainAxis(0).java2DToValue(p.getX(), dataArea, wotPlot.getDomainAxisEdge());
boolean isLeft = (p.getX() < (dataArea.getMaxX() - dataArea.getMinX()) / 2) ? true : false;
if (isLeft) {
wotMarker.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
wotMarker.setLabelTextAnchor(TextAnchor.TOP_LEFT);
}
else {
wotMarker.setLabelAnchor(RectangleAnchor.TOP_LEFT);
wotMarker.setLabelTextAnchor(TextAnchor.TOP_RIGHT);
}
XYSeriesCollection dataset;
NumberAxis rangeAxis;
boolean show = false;
for (int i = 0; i < wotPlot.getDatasetCount(); ++i) {
dataset = (XYSeriesCollection)wotPlot.getDataset(i);
if (dataset != null && dataset.getSeriesCount() > 0) {
show = true;
rangeAxis = (NumberAxis)wotPlot.getRangeAxis(i);
y = rangeAxis.java2DToValue(p.getY(), dataArea, wotPlot.getRangeAxisEdge());
wotMarker.addLabel(rangeAxis.getLabel() + ": " + df.format(y), new Color(255 - i, 255, 255), false);
}
}
if (show) {
wotMarker.setValue(x);
y = wotPlot.getRangeAxis().java2DToValue(p.getY(), dataArea, wotPlot.getRangeAxisEdge());
Marker yMarker = new ValueMarker(y);
yMarker.setPaint(Color.WHITE);
wotPlot.addRangeMarker(yMarker);
}
wotChartPanel.repaint();
}
catch (Exception ex) {
ex.printStackTrace();
logger.error(ex);
}
}
@Override
public void chartMouseClicked(ChartMouseEvent event) {
wotChartPanel.requestFocusInWindow();
}
});
wotChartPanel.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
if (!wotChartPanel.hasFocus())
return;
int keyCode = e.getKeyCode();
if (keyCode < KeyEvent.VK_LEFT || keyCode > KeyEvent.VK_DOWN)
return;
ValueAxis axis = null;
if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT)
axis = ((XYPlot)wotChartPanel.getChart().getXYPlot()).getDomainAxis();
else
axis = ((XYPlot)wotChartPanel.getChart().getXYPlot()).getRangeAxis();
if (axis != null) {
double delta = (axis.getUpperBound()- axis.getLowerBound()) / 100.0;
if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_DOWN)
axis.setRange(axis.getLowerBound()- delta, axis.getUpperBound() - delta);
else if (keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_RIGHT)
axis.setRange(axis.getLowerBound() + delta, axis.getUpperBound() + delta);
}
}
public void keyReleased(KeyEvent arg0) { }
public void keyTyped(KeyEvent arg0) { }
});
}
//////////////////////////////////////////////////////////////////////////////////////
// CREATE USAGE TAB
//////////////////////////////////////////////////////////////////////////////////////
private void createUsageTab() {
JTextPane usageTextArea = new JTextPane();
usageTextArea.setMargin(insets10);
usageTextArea.setContentType("text/html");
usageTextArea.setText(usage());
usageTextArea.setEditable(false);
usageTextArea.setCaretPosition(0);
JScrollPane textScrollPane = new JScrollPane(usageTextArea);
textScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
textScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
add(textScrollPane, "<html><div style='text-align: center;'>U<br>s<br>a<br>g<br>e</div></html>");
}
private String usage() {
ResourceBundle bundle;
bundle = ResourceBundle.getBundle("com.vgi.mafscaling.logview");
return bundle.getString("usage");
}
//////////////////////////////////////////////////////////////////////////////////////
// WORK FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////
private void initColors() {
colors.clear();
colors.push(new Color(255,101,0));
colors.push(new Color(255,154,0));
colors.push(new Color(255,207,0));
colors.push(new Color(156,207,0));
colors.push(new Color(49,207,206));
colors.push(new Color(49,101,255));
colors.push(new Color(255,207,156));
colors.push(new Color(206,154,255));
colors.push(new Color(255,154,206));
colors.push(new Color(156,207,255));
colors.push(new Color(255,255,156));
colors.push(new Color(206,255,206));
colors.push(new Color(206,255,255));
colors.push(new Color(0,207,255));
colors.push(new Color(0,0,255));
colors.push(new Color(0,130,132));
colors.push(new Color(132,0,0));
colors.push(new Color(132,0,132));
colors.push(new Color(0,255,255));
colors.push(new Color(255,255,0));
colors.push(new Color(255,0,255));
colors.push(new Color(0,0,132));
colors.push(new Color(206,207,255));
colors.push(new Color(0,101,206));
colors.push(new Color(255,130,132));
colors.push(new Color(99,0,99));
colors.push(new Color(206,255,255));
colors.push(new Color(255,255,206));
colors.push(new Color(156,48,99));
colors.push(new Color(156,154,255));
colors.push(new Color(221,160,221));
colors.push(new Color(176,196,222));
colors.push(new Color(32,178,170));
colors.push(new Color(250,240,230));
colors.push(new Color(210,180,140));
colors.push(new Color(143,188,139));
colors.push(new Color(219,220,37));
colors.push(new Color(42,214,42));
colors.push(new Color(241,104,60));
colors.push(new Color(29,139,209));
/*
colors.push(Color.decode("#FF6500"));
colors.push(Color.decode("#FF9A00"));
colors.push(Color.decode("#FFCF00"));
colors.push(Color.decode("#9CCF00"));
colors.push(Color.decode("#31CFCE"));
colors.push(Color.decode("#3165FF"));
colors.push(Color.decode("#FFCF9C"));
colors.push(Color.decode("#CE9AFF"));
colors.push(Color.decode("#FF9ACE"));
colors.push(Color.decode("#9CCFFF"));
colors.push(Color.decode("#FFFF9C"));
colors.push(Color.decode("#CEFFCE"));
colors.push(Color.decode("#CEFFFF"));
colors.push(Color.decode("#00CFFF"));
colors.push(Color.decode("#0000FF"));
colors.push(Color.decode("#008284"));
colors.push(Color.decode("#840000"));
colors.push(Color.decode("#840084"));
colors.push(Color.decode("#00FFFF"));
colors.push(Color.decode("#FFFF00"));
colors.push(Color.decode("#FF00FF"));
colors.push(Color.decode("#000084"));
colors.push(Color.decode("#CECFFF"));
colors.push(Color.decode("#0065CE"));
colors.push(Color.decode("#FF8284"));
colors.push(Color.decode("#630063"));
colors.push(Color.decode("#CEFFFF"));
colors.push(Color.decode("#FFFFCE"));
colors.push(Color.decode("#9C3063"));
colors.push(Color.decode("#9C9AFF"));
colors.push(Color.decode("#DDA0DD"));
colors.push(Color.decode("#B0C4DE"));
colors.push(Color.decode("#20B2AA"));
colors.push(Color.decode("#FAF0E6"));
colors.push(Color.decode("#D2B48C"));
colors.push(Color.decode("#8FBC8B"));
colors.push(Color.decode("#DBDC25"));
colors.push(Color.decode("#2AD62A"));
colors.push(Color.decode("#F1683C"));
colors.push(Color.decode("#1D8BD1"));
*/
}
private JButton addToolbarButton(String tooltip, String image) {
JButton button = new JButton(new ImageIcon(this.getClass().getResource(image)));
button.setToolTipText(tooltip);
button.setMargin(insets0);
button.setAlignmentY(Component.CENTER_ALIGNMENT);
button.addActionListener(this);
toolBar.add(button);
return button;
}
private void addXYSeries(TableModel model, int column, String name, Color color) {
setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
XYSeries series;
if (column == rpmCol) {
series = rpmDataset.getSeries(0);
((NumberAxis)plot.getRangeAxis(0)).setStandardTickUnits(NumberAxis.createIntegerTickUnits());
plot.getRangeAxis(0).setTickLabelsVisible(true);
rpmPlotRenderer.setSeriesPaint(0, color);
rpmPlotRenderer.setSeriesVisible(0, true);
}
else {
series = dataset.getSeries(column);
plot.getRangeAxis(1).setTickLabelsVisible(true);
plotRenderer.setSeriesPaint(column, color);
plotRenderer.setSeriesVisible(column, true);
displCount += 1;
}
if (xMarker.count() > 0)
xMarker.addLabel(series.getDescription() + ": " + series.getY((int) xMarker.getValue()), color, true);
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
chartPanel.revalidate();
}
private void removeXYSeries(int column) {
if (column == rpmCol) {
((NumberAxis)plot.getRangeAxis(0)).setStandardTickUnits(new StandardTickUnitSource());
plot.getRangeAxis(0).setTickLabelsVisible(false);
rpmPlotRenderer.setSeriesVisible(0, false);
xMarker.removeLabel(rpmPlotRenderer.getSeriesPaint(0));
}
else {
displCount -= 1;
if (displCount == 0)
plot.getRangeAxis(1).setTickLabelsVisible(false);
plotRenderer.setSeriesVisible(column, false);
xMarker.removeLabel(plotRenderer.getSeriesPaint(column));
}
}
private void sortAscending(int column) {
logDataTable.sortByColumn(column, true) ;
}
private void sortDescending(int column) {
logDataTable.sortByColumn(column, false) ;
}
private void convertTimeToMsec() {
String val;
boolean timeColFound = false;
for (int i = 0; i < logDataTable.getColumnCount() && !timeColFound; ++i) {
String colName = logDataTable.getColumn(i).getHeaderValue().toString();
if (colName.toLowerCase().matches(timeMatchString)) {
if (logDataTable.getRowCount() > 0) {
val = (String)logDataTable.getValueAt(0, i);
if (val.matches(Utils.tmRegex)) {
long time = 0;
long tmbase = 0;
for (int j = 0; j < logDataTable.getRowCount(); ++j) {
try {
if (j == 0)
Utils.resetBaseTime((String)logDataTable.getValueAt(j, i));
time = Utils.parseTime((String)logDataTable.getValueAt(j, i));
if (tmbase == 0) {
tmbase = time;
if (time > 1000)
time = 0;
}
logDataTable.setValueAt(String.valueOf(time), j, i);
}
catch (Exception e) {
JOptionPane.showMessageDialog(null, "Invalid numeric value in column " + colName + ", row " + (j + 1), "Invalid value", JOptionPane.ERROR_MESSAGE);
return;
}
}
}
}
}
}
}
private void convertOnOffToNumMsec() {
String val;
for (int i = logDataTable.getColumnCount() - 1; i >= 0 ; --i) {
if (logDataTable.getRowCount() > 0) {
val = (String)logDataTable.getValueAt(0, i);
if (val.matches(Utils.onOffRegex)) {
for (int j = 0; j < logDataTable.getRowCount(); ++j) {
val = (String)logDataTable.getValueAt(j, i);
logDataTable.setValueAt(String.valueOf(Utils.parseValue(val)), j, i);
}
}
else if (!Pattern.matches(Utils.fpRegex, val))
logDataTable.removeColumn(logDataTable.getColumn(i));
}
}
}
private void selectLogFile() {
fileChooser.setMultiSelectionEnabled(false);
if (JFileChooser.APPROVE_OPTION != fileChooser.showOpenDialog(this))
return;
loadLogFile();
}
private void loadLogFile() {
// close log player
if (logPlayWindow != null)
disposeLogView();
// process log file
File file = fileChooser.getSelectedFile();
Properties prop = new Properties();
prop.put("delimiter", ",");
prop.put("firstRowHasColumnNames", "true");
setCursor(new Cursor(Cursor.WAIT_CURSOR));
logDataTable.filter(null);
filterText.setText("");
Column col;
String colName;
String lcColName;
String val;
try {
for (int i = 0; i < logDataTable.getColumnCount(); ++i) {
try {
CheckboxHeaderRenderer cbr = (CheckboxHeaderRenderer)logDataTable.getColumn(i).getHeaderRenderer();
logDataTable.getTableHeader().removeMouseListener(cbr.getMouseListener());
}
catch (Exception e) {
}
}
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(file.getAbsoluteFile()), Config.getEncoding()));
String line = null;
br.mark(1024);
while ((line = br.readLine()) != null && !line.contains(",")) {
br.mark(1024);
continue;
}
br.reset();
logDataTable.refresh(br, prop);
// Below is a hack code to check and convert time column hh:mm:ss.sss to msec number
convertTimeToMsec();
// Below is a hack code to check and convert column(s) with on/off values to number
convertOnOffToNumMsec();
}
catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
return;
}
finally {
if (br != null) {
try {
br.close();
}
catch (IOException e) {
logger.error(e);
}
}
}
CheckboxHeaderRenderer renderer;
Component comp;
XYSeries series;
selectionCombo.removeAllItems();
listModel.removeAllElements();
xAxisColumn.removeAllItems();
yAxisColumn.removeAllItems();
plotsColumn.removeAllItems();
xAxisColumn.addItem("");
yAxisColumn.addItem("");
plotsColumn.setText("");
plot3d.removeAllPlots();
rpmDataset.removeAllSeries();
dataset.removeAllSeries();
xMarker.clearLabels(true);
rpmCol = -1;
displCount = 0;
JTableHeader tableHeader = logDataTable.getTableHeader();
TreeSet<String> sortedColumns = new TreeSet<String>();
for (int i = 0; i < logDataTable.getColumnCount(); ++i) {
col = logDataTable.getColumn(i);
renderer = new CheckboxHeaderRenderer(i + 1, tableHeader);
col.setHeaderRenderer(renderer);
colName = col.getHeaderValue().toString();
sortedColumns.add(colName);
comp = renderer.getTableCellRendererComponent(logDataTable.getTable(), colName, false, false, 0, 0);
col.setPreferredWidth(comp.getPreferredSize().width + 4);
series = new XYSeries(colName);
series.setDescription(colName);
lcColName = colName.toLowerCase();
dataset.addSeries(series);
plotRenderer.setSeriesShapesVisible(i, false);
plotRenderer.setSeriesVisible(i, false);
if (rpmDataset.getSeriesCount() == 0 && (lcColName.matches(rpmMatchString) || lcColName.matches(engineSpeedMatchString))) {
rpmDataset.addSeries(series);
rpmPlotRenderer.setSeriesShapesVisible(0, false);
rpmPlotRenderer.setSeriesVisible(0, false);
rpmCol = i;
}
for (int j = 0; j < logDataTable.getRowCount(); ++j) {
try {
val = (String)logDataTable.getValueAt(j, i);
series.add(j, Double.valueOf(val), false);
}
catch (Exception e) {
JOptionPane.showMessageDialog(null, "Invalid numeric value in column " + colName + ", row " + (j + 1), "Invalid value", JOptionPane.ERROR_MESSAGE);
return;
}
}
series.fireSeriesChanged();
}
for (String s : sortedColumns) {
xAxisColumn.addItem(s);
yAxisColumn.addItem(s);
plotsColumn.addItem(s);
selectionCombo.addItem(s);
renderer = (CheckboxHeaderRenderer)logDataTable.getColumnByHeaderName(s).getHeaderRenderer();
listModel.addElement(new JLabel(s, renderer.getCheckIcon(), JLabel.LEFT));
}
if (logDataTable.getControlPanel().getComponentCount() > tableControlPanelNumComponents)
logDataTable.getControlPanel().remove(tableControlPanelNumComponents);
logDataTable.getControlPanel().add(new JLabel(" [" + file.getName() + "]"));
initColors();
}
catch (Exception ex) {
ex.printStackTrace();
logger.error(ex);
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
public ChartPanel getChartPanel() {
return chartPanel;
}
private void updateChart() {
if (logDataTable.getColumnCount() != dataset.getSeriesCount())
return;
Column col;
String colName;
String val;
XYSeries series;
int seriesIdx = 0;
for (int i = 0; i < logDataTable.getColumnCount(); ++i) {
int colIdx = logDataTable.getCurrentIndexForOriginalColumn(i);
col = logDataTable.getColumn(colIdx);
colName = col.getHeaderValue().toString();
series = dataset.getSeries(seriesIdx++);
if (!series.getDescription().equals(colName)) {
JOptionPane.showMessageDialog(null, "Invalid series found for the column index " + colIdx + ": series name " + series.getDescription() + " doesn't match column name " + colName, "Invalid value", JOptionPane.ERROR_MESSAGE);
return;
}
series.clear();
for (int j = 0; j < logDataTable.getRowCount(); ++j) {
try {
val = (String)logDataTable.getValueAt(j, colIdx);
series.add(j, Double.valueOf(val), false);
}
catch (Exception e) {
JOptionPane.showMessageDialog(null, "Invalid numeric value in column " + colName + ", row " + (j + 1), "Invalid value", JOptionPane.ERROR_MESSAGE);
return;
}
}
series.fireSeriesChanged();
}
chartPanel.repaint();
}
private void view3dPlots() {
if (xAxisColumn.getSelectedItem() == null ||
xAxisColumn.getSelectedItem().toString().isEmpty() ||
yAxisColumn.getSelectedItem() == null ||
yAxisColumn.getSelectedItem().toString().isEmpty() ||
plotsColumn.getSelectedItems() == null)
return;
plot3d.removeAllPlots();
String val;
String xAxisColName = (String)xAxisColumn.getSelectedItem();
String yAxisColName = (String)yAxisColumn.getSelectedItem();
List<String> dataColNames = plotsColumn.getSelectedItems();
if (dataColNames.size() > maxNumPlots) {
JOptionPane.showMessageDialog(null, "Sorry, only " + maxNumPlots + " plots are supported. More plots will make the graph too slow.", "Too many parameters", JOptionPane.ERROR_MESSAGE);
return;
}
int xColIdx = logDataTable.getColumnByHeaderName(xAxisColName).getModelIndex() - 1;
xColIdx = logDataTable.getCurrentIndexForOriginalColumn(xColIdx);
int yColIdx = logDataTable.getColumnByHeaderName(yAxisColName).getModelIndex() - 1;
yColIdx = logDataTable.getCurrentIndexForOriginalColumn(yColIdx);
ArrayList<Color> colorsArray = new ArrayList<Color>();
colorsArray.add(Color.BLUE);
colorsArray.add(Color.RED);
colorsArray.add(Color.GREEN);
colorsArray.add(Color.ORANGE);
colorsArray.add(Color.GRAY);
double x, y, z;
XYZ xyz;
for (int j = 0; j < dataColNames.size(); ++j) {
HashSet<XYZ> uniqueXYZ = new HashSet<XYZ>();
int zColIdx = logDataTable.getColumnByHeaderName(dataColNames.get(j)).getModelIndex() - 1;
zColIdx = logDataTable.getCurrentIndexForOriginalColumn(zColIdx);
int count = 0;
double[][] xyzArrayTemp = new double[logDataTable.getRowCount()][3];
for (int i = 0; i < logDataTable.getRowCount(); ++i) {
val = (String)logDataTable.getValueAt(i, xColIdx);
x = Double.valueOf(val);
val = (String)logDataTable.getValueAt(i, yColIdx);
y = Double.valueOf(val);
val = (String)logDataTable.getValueAt(i, zColIdx);
z = Double.valueOf(val);
xyz = new XYZ(x, y, z);
if (uniqueXYZ.contains(xyz))
continue;
uniqueXYZ.add(xyz);
xyzArrayTemp[count][0] = x;
xyzArrayTemp[count][1] = y;
xyzArrayTemp[count][2] = z;
count += 1;
}
double[][] xyzArray = new double[uniqueXYZ.size()][3];
for (int k = 0; k < xyzArray.length; ++k)
System.arraycopy(xyzArrayTemp[k], 0, xyzArray[k], 0, 3);
plot3d.addScatterPlot(dataColNames.get(j), colorsArray.get(j), xyzArray);
}
plot3d.setAxisLabel(0, xAxisColumn.getSelectedItem().toString());
plot3d.setAxisLabel(1, yAxisColumn.getSelectedItem().toString());
plot3d.setAxisLabel(2, plotsColumn.getSelectedItemsString());
}
private boolean getColumnsFilters(ArrayList<String> columns) {
boolean ret = true;
String logThtlAngleColName = Config.getLogThrottleAngleColumnName();
logRpmColName = Config.getLogRpmColumnName();
logTimeColName = Config.getLogTimeColumnName();
logThtlAngleColIdx = columns.indexOf(logThtlAngleColName);
int logRpmColIdx = columns.indexOf(logRpmColName);
int logTimeColIdx = columns.indexOf(logTimeColName);
if (logRpmColIdx == -1) {
String lcColName;
for (int i = 0; i < columns.size(); ++i) {
lcColName = columns.get(i).toLowerCase();
if (lcColName.matches(rpmMatchString) || lcColName.matches(engineSpeedMatchString)) {
logRpmColIdx = i;
logRpmColName = columns.get(i);
}
}
}
if (logTimeColIdx == -1) {
String lcColName;
for (int i = 0; i < columns.size(); ++i) {
lcColName = columns.get(i).toLowerCase();
if (lcColName.toLowerCase().matches(timeMatchString)) {
logTimeColIdx = i;
logTimeColName = columns.get(i);
}
}
}
wotPoint = Config.getLogWOTStationaryPointValue();
JComboBox<String> thrlColumn = new JComboBox<String>();
JComboBox<String> rpmColumn = new JComboBox<String>();
JComboBox<String> timeColumn = new JComboBox<String>();
JSpinner wotPointSpinner = new JSpinner(new SpinnerNumberModel(wotPoint, 50, 100, 5));
TreeSet<String> sortedColumns = new TreeSet<String>(columns);
for (String col : sortedColumns) {
thrlColumn.addItem(col);
rpmColumn.addItem(col);
timeColumn.addItem(col);
}
thrlColumn.setSelectedItem(logThtlAngleColName);
rpmColumn.setSelectedItem(logRpmColName);
timeColumn.setSelectedItem(logTimeColName);
JPanel selectionPanel = new JPanel();
selectionPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
selectionPanel.setLayout(new GridLayout(0, 2, 5, 7));
selectionPanel.add(new JLabel(ColumnsFiltersSelection.timeLabelText, JLabel.RIGHT));
selectionPanel.add(timeColumn);
selectionPanel.add(new JLabel(ColumnsFiltersSelection.rpmLabelText, JLabel.RIGHT));
selectionPanel.add(rpmColumn);
selectionPanel.add(new JLabel(ColumnsFiltersSelection.thrtlAngleLabelText, JLabel.RIGHT));
selectionPanel.add(thrlColumn);
selectionPanel.add(new JLabel(ColumnsFiltersSelection.wotStationaryLabelText, JLabel.RIGHT));
selectionPanel.add(wotPointSpinner);
if (JOptionPane.OK_OPTION != JOptionPane.showConfirmDialog(null, selectionPanel, "Settings", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE))
ret = false;
else {
logThtlAngleColName = thrlColumn.getSelectedItem().toString();
logRpmColName = rpmColumn.getSelectedItem().toString();
logTimeColName = timeColumn.getSelectedItem().toString();
wotPoint = Integer.valueOf(wotPointSpinner.getValue().toString());
logThtlAngleColIdx = columns.indexOf(logThtlAngleColName);
logRpmColIdx = columns.indexOf(logRpmColName);
logTimeColIdx = columns.indexOf(logTimeColName);
Config.setLogWOTStationaryPointValue(wotPoint);
if (logThtlAngleColIdx == -1) {
Config.setLogThrottleAngleColumnName(Config.NO_NAME);
ret = false;
}
else
Config.setLogThrottleAngleColumnName(logThtlAngleColName);
if (logRpmColIdx == -1) {
Config.setLogRpmColumnName(Config.NO_NAME);
ret = false;
}
else
Config.setLogRpmColumnName(logRpmColName);
if (logTimeColIdx == -1) {
Config.setLogTimeColumnName(Config.NO_NAME);
ret = false;
}
else
Config.setLogTimeColumnName(logTimeColName);
}
return ret;
}
private void selectWotLogFiles() {
fileChooser.setMultiSelectionEnabled(true);
if (JFileChooser.APPROVE_OPTION != fileChooser.showOpenDialog(this))
return;
loadWotLogFiles();
}
private void loadWotLogFiles() {
File[] files = fileChooser.getSelectedFiles();
if (files.length < 1)
return;
filesData = new HashMap<String, ArrayList<HashMap<String, ArrayList<Double>>>>();
TreeSet<String> columns = new TreeSet<String>();
ArrayList<String> colNames = null;
DefaultMutableTreeNode root = (DefaultMutableTreeNode)wotTree.getModel().getRoot();
root.removeAllChildren();
((DefaultTreeModel )wotTree.getModel()).reload(root);
wotPlotsColumn.removeAllItems();
wotPlotsColumn.setText("");
clearWotPlots();
double val;
int i = 0;
int row = 0;
for (File file : files) {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(file.getAbsoluteFile()), Config.getEncoding()));
String line = null;
String [] elements = null;
while ((line = br.readLine()) != null && (elements = line.split(Utils.fileFieldSplitter, -1)) != null && elements.length < 2)
continue;
if (line.charAt(line.length() - 1) == ',')
Arrays.copyOf(elements, elements.length - 1);
colNames = new ArrayList<String>(Arrays.asList(elements));
if (false == getColumnsFilters(colNames))
continue;
DefaultMutableTreeNode fileNode = new DefaultMutableTreeNode("<html><u>" + file.getName() + "</u></html>");
ArrayList<HashMap<String, ArrayList<Double>>> pulls = new ArrayList<HashMap<String, ArrayList<Double>>>();
HashMap<String, ArrayList<Double>> pullData = new HashMap<String, ArrayList<Double>>();
ArrayList<Double> columnData;
String[] flds;
row = 0;
int pullRows = 0;
boolean wotFlag = true;
while ((line = br.readLine()) != null) {
if (line.length() > 0 && line.charAt(line.length() - 1) == ',')
line = line.substring(0, line.length() - 1);
flds = line.split(Utils.fileFieldSplitter, -1);
val = Double.valueOf(flds[logThtlAngleColIdx]);
if (row == 0 && val < 99)
wotFlag = false;
if (val < wotPoint) {
if (wotFlag == true) {
wotFlag = false;
if (pullRows >= 10) {
pulls.add(pullData);
pullData = new HashMap<String, ArrayList<Double>>();
fileNode.add(new DefaultMutableTreeNode(new CheckBoxNodeData(pullIndexReplaceString + pulls.size(), true)));
}
}
}
else {
boolean newPullData = false;
if (wotFlag == false || row == 0) {
wotFlag = true;
newPullData = true;
pullRows = 0;
}
pullRows += 1;
for (i = 0; i < colNames.size(); ++i) {
if (newPullData) {
columnData = new ArrayList<Double>();
pullData.put(colNames.get(i), columnData);
}
else
columnData = pullData.get(colNames.get(i));
if (flds[i].matches(Utils.tmRegex)) {
if (row == 0)
Utils.resetBaseTime(flds[i]);
columnData.add((double)Utils.parseTime(flds[i]));
}
else
columnData.add(Utils.parseValue(flds[i]));
}
}
row += 1;
}
if (wotFlag == true) {
if (pullRows >= 10) {
pulls.add(pullData);
pullData = new HashMap<String, ArrayList<Double>>();
fileNode.add(new DefaultMutableTreeNode(new CheckBoxNodeData(pullIndexReplaceString + pulls.size(), true)));
}
}
if (pulls.size() > 0) {
root.add(fileNode);
TreePath path = new TreePath(root);
wotTree.expandPath(path.pathByAddingChild(fileNode));
filesData.put(file.getName(), pulls);
columns.addAll(colNames);
}
}
catch (NumberFormatException ne) {
logger.error(ne);
JOptionPane.showMessageDialog(null, "Error parsing number at " + file.getName() + ", column " + colNames.get(i) + " line " + row + ": " + ne, "Error processing file", JOptionPane.ERROR_MESSAGE);
return;
}
catch (Exception e) {
logger.error(e);
JOptionPane.showMessageDialog(null, e.getMessage(), "Error processing file " + file.getName(), JOptionPane.ERROR_MESSAGE);
return;
}
finally {
if (br != null) {
try {
br.close();
}
catch (IOException e) {
logger.error(e);
}
}
}
}
if (columns.size() > 0) {
for (String col : columns)
wotPlotsColumn.addItem(col);
((DefaultTreeModel )wotTree.getModel()).reload(root);
for (row = 0; row < wotTree.getRowCount(); ++row)
wotTree.expandRow(row);
}
else {
JOptionPane.showMessageDialog(null, "No WOT pulls were found in the log file(s)", "Oops", JOptionPane.INFORMATION_MESSAGE);
}
}
protected void clearWotPlots() {
for (int i = 0; i < wotPlot.getDatasetCount(); ++i) {
XYSeriesCollection dataset = (XYSeriesCollection)wotPlot.getDataset(i);
if (dataset != null) {
dataset.removeAllSeries();
wotPlot.setDataset(i, null);
wotPlot.setRangeAxis(i, null);
}
}
wotPlot.clearRangeMarkers();
wotMarker.clearLabels(true);
}
private void viewWotPlotsByTime() {
List<String> dataColNames = wotPlotsColumn.getSelectedItems();
if (dataColNames == null || dataColNames.size() == 0) {
JOptionPane.showMessageDialog(null, "Please select columns to plot", "Invalid parameters", JOptionPane.ERROR_MESSAGE);
return;
}
clearWotPlots();
ArrayList<HashMap<String, ArrayList<Double>>> filePulls;
HashMap<String, ArrayList<Double>> pullData;
ArrayList<Double> rpmData;
ArrayList<Double> timeData;
ArrayList<Double> colData = null;
DefaultMutableTreeNode fileNode;
CheckBoxNodeData pullNode;
String fileName;
String pullName;
int pullIdx;
int idx;
int rpm;
int maxrpm = 0;
double time = 0;
double newtime = 0;
double maxtime = 0;
double timeOffset = 0;
setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
// sort all pulls by RPM
TreeMap<Integer, ArrayList<HashMap<String, HashMap<String, ArrayList<Double>>>>> pullsByRpm = new TreeMap<Integer, ArrayList<HashMap<String, HashMap<String, ArrayList<Double>>>>>();
ArrayList<HashMap<String, HashMap<String, ArrayList<Double>>>> pulls;
DefaultMutableTreeNode root = (DefaultMutableTreeNode)wotTree.getModel().getRoot();
for (idx = 0; idx < root.getChildCount(); ++idx) {
fileNode = (DefaultMutableTreeNode)root.getChildAt(idx);
fileName = fileNode.getUserObject().toString().replaceAll(fileNameReplaceString, "");
for (int j = 0; j < fileNode.getChildCount(); ++j) {
pullNode = (CheckBoxNodeData)((DefaultMutableTreeNode)fileNode.getChildAt(j)).getUserObject();
if (!pullNode.isChecked())
continue;
pullName = pullNode.getText();
filePulls = filesData.get(fileName);
pullIdx = Integer.parseInt(pullName.replaceAll(pullIndexReplaceString, "")) - 1;
pullData = filePulls.get(pullIdx);
pullName = " [" + pullName + ": " + fileName + "]";
HashMap<String, HashMap<String, ArrayList<Double>>> pullDataByName = new HashMap<String, HashMap<String, ArrayList<Double>>>();
pullDataByName.put(pullName, pullData);
rpmData = pullData.get(logRpmColName);
rpm = rpmData.get(0).intValue();
pulls = pullsByRpm.get(rpm);
if (pulls == null) {
pulls = new ArrayList<HashMap<String, HashMap<String, ArrayList<Double>>>>();
pullsByRpm.put(rpm, pulls);
}
pulls.add(pullDataByName);
}
}
// Reset pulls time by aligning RPM
ArrayList<HashMap<String, HashMap<String, ArrayList<Double>>>> allpulls = new ArrayList<HashMap<String, HashMap<String, ArrayList<Double>>>>();
while (pullsByRpm.size() > 0) {
time = newtime;
newtime = 0;
rpm = pullsByRpm.firstKey();
maxrpm = rpm;
pulls = pullsByRpm.remove(rpm);
for (idx = 0; idx < pulls.size(); ++idx) {
pullData = (pulls.get(idx)).entrySet().iterator().next().getValue();
rpmData = pullData.get(logRpmColName);
timeData = pullData.get(logTimeColName);
colData = new ArrayList<Double>();
for (int j = 0; j < rpmData.size(); ++j) {
double tm = timeData.get(j);
if (j == 0)
timeOffset = tm - time;
tm = tm - timeOffset;
colData.add(tm);
rpm = rpmData.get(j).intValue();
if (pullsByRpm.size() > 0 && newtime == 0 && rpm >= pullsByRpm.firstKey())
newtime = tm;
}
maxrpm = Math.max(maxrpm, rpmData.get(rpmData.size() - 1).intValue());
maxtime = Math.max(maxtime, colData.get(colData.size() - 1));
pullData.put("xaxis", colData);
}
if (pullsByRpm.size() > 0 && newtime == 0)
newtime = (maxtime * pullsByRpm.firstKey()) / maxrpm;
allpulls.addAll(pulls);
}
// Plot data
for (int i = 0; i < dataColNames.size(); ++i) {
String yAxisColName = dataColNames.get(i);
XYLineAndShapeRenderer lineRenderer = new XYLineAndShapeRenderer();
XYSeriesCollection dataset = new XYSeriesCollection();
for (idx = 0; idx < allpulls.size(); ++idx) {
Map.Entry<String, HashMap<String, ArrayList<Double>>> keyval = allpulls.get(idx).entrySet().iterator().next();
pullName = yAxisColName + keyval.getKey();
pullData = keyval.getValue();
timeData = pullData.get("xaxis");
colData = pullData.get(yAxisColName);
if (colData != null) {
XYSeries series = new XYSeries(pullName);
for (int k = 0; k < timeData.size(); ++k)
series.add(Double.valueOf(timeData.get(k)), Double.valueOf(colData.get(k)));
dataset.addSeries(series);
lineRenderer.setSeriesShapesVisible(dataset.getSeriesCount() - 1, showWotCurvePoints);
}
}
NumberAxis yAxis = new NumberAxis(yAxisColName);
yAxis.setAutoRangeIncludesZero(false);
yAxis.setTickLabelPaint(Color.WHITE);
yAxis.setLabelPaint(Color.LIGHT_GRAY);
wotPlot.setRenderer(i, lineRenderer);
wotPlot.setRangeAxis(i, yAxis, false);
wotPlot.setDataset(i, dataset);
wotPlot.mapDatasetToRangeAxis(i, i);
wotPlot.mapDatasetToDomainAxis(i, 0);
wotPlot.setRangeAxisLocation(i, (i % 2 == 0 ? AxisLocation.BOTTOM_OR_LEFT : AxisLocation.BOTTOM_OR_RIGHT));
}
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
private void viewWotPlotsByRpm(boolean skipDrops) {
List<String> dataColNames = wotPlotsColumn.getSelectedItems();
if (dataColNames == null || dataColNames.size() == 0) {
JOptionPane.showMessageDialog(null, "Please select columns to plot", "Invalid parameters", JOptionPane.ERROR_MESSAGE);
return;
}
clearWotPlots();
ArrayList<HashMap<String, ArrayList<Double>>> filePulls;
HashMap<String, ArrayList<Double>> pullData;
ArrayList<Double> rpmData;
ArrayList<Double> colData;
DefaultMutableTreeNode fileNode;
CheckBoxNodeData pullNode;
String fileName;
String pullName;
int pullIdx;
setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
for (int i = 0; i < dataColNames.size(); ++i) {
String yAxisColName = dataColNames.get(i);
XYLineAndShapeRenderer lineRenderer = new XYLineAndShapeRenderer();
XYSeriesCollection dataset = new XYSeriesCollection();
DefaultMutableTreeNode root = (DefaultMutableTreeNode)wotTree.getModel().getRoot();
for (int idx = 0; idx < root.getChildCount(); ++idx) {
fileNode = (DefaultMutableTreeNode)root.getChildAt(idx);
fileName = fileNode.getUserObject().toString().replaceAll(fileNameReplaceString, "");
for (int j = 0; j < fileNode.getChildCount(); ++j) {
pullNode = (CheckBoxNodeData)((DefaultMutableTreeNode)fileNode.getChildAt(j)).getUserObject();
if (!pullNode.isChecked())
continue;
pullName = pullNode.getText();
filePulls = filesData.get(fileName);
pullIdx = Integer.parseInt(pullName.replaceAll(pullIndexReplaceString, "")) - 1;
pullData = filePulls.get(pullIdx);
rpmData = pullData.get(logRpmColName);
colData = pullData.get(yAxisColName);
if (colData != null) {
XYSeries series = new XYSeries(yAxisColName + " [" + pullName + ": " + fileName + "]");
for (int k = 0; k < rpmData.size(); ++k) {
if (skipDrops) {
if (k > 0 && rpmData.get(k) > rpmData.get(k - 1))
series.add(Double.valueOf(rpmData.get(k)), Double.valueOf(colData.get(k)));
}
else
series.add(Double.valueOf(rpmData.get(k)), Double.valueOf(colData.get(k)));
}
dataset.addSeries(series);
lineRenderer.setSeriesShapesVisible(dataset.getSeriesCount() - 1, showWotCurvePoints);
}
}
}
NumberAxis yAxis = new NumberAxis(yAxisColName);
yAxis.setAutoRangeIncludesZero(false);
yAxis.setTickLabelPaint(Color.WHITE);
yAxis.setLabelPaint(Color.LIGHT_GRAY);
wotPlot.setRenderer(i, lineRenderer);
wotPlot.setRangeAxis(i, yAxis, false);
wotPlot.setDataset(i, dataset);
wotPlot.mapDatasetToRangeAxis(i, i);
wotPlot.mapDatasetToDomainAxis(i, 0);
wotPlot.setRangeAxisLocation(i, (i % 2 == 0 ? AxisLocation.BOTTOM_OR_LEFT : AxisLocation.BOTTOM_OR_RIGHT));
}
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
public boolean setMarkers(double x, boolean isLeft) {
xMarker.clearLabels(false);
if (x < 0 || x >= logDataTable.getRowCount())
return false;
XYSeries series = null;
if (isLeft) {
xMarker.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
xMarker.setLabelTextAnchor(TextAnchor.TOP_LEFT);
}
else {
xMarker.setLabelAnchor(RectangleAnchor.TOP_LEFT);
xMarker.setLabelTextAnchor(TextAnchor.TOP_RIGHT);
}
if (rpmDataset.getSeriesCount() > 0 && rpmPlotRenderer.isSeriesVisible(0)) {
series = rpmDataset.getSeries(0);
xMarker.addLabel(series.getDescription() + ": " + series.getY((int)x), rpmPlotRenderer.getSeriesPaint(0), false);
}
for (int i = 0; i < dataset.getSeriesCount(); ++i) {
if (plotRenderer.isSeriesVisible(i)) {
series = dataset.getSeries(i);
xMarker.addLabel(series.getDescription() + ": " + series.getY((int)x), plotRenderer.getSeriesPaint(i), false);
}
}
xMarker.setValue(x);
return (series != null);
}
private void exportSelectedWotPulls() {
ArrayList<HashMap<String, ArrayList<Double>>> filePulls;
HashMap<String, ArrayList<Double>> pullData;
DefaultMutableTreeNode fileNode;
CheckBoxNodeData pullNode;
String fileName = null;
String nodeName = null;
String dirName = null;
int pullIdx;
int cnt;
int i, j;
setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
DefaultMutableTreeNode root = (DefaultMutableTreeNode)wotTree.getModel().getRoot();
for (int idx = 0; idx < root.getChildCount(); ++idx) {
fileNode = (DefaultMutableTreeNode)root.getChildAt(idx);
fileName = fileNode.getUserObject().toString().replaceAll(fileNameReplaceString, "");
for (cnt = 0; cnt < fileNode.getChildCount(); ++cnt) {
pullNode = (CheckBoxNodeData)((DefaultMutableTreeNode)fileNode.getChildAt(cnt)).getUserObject();
if (!pullNode.isChecked())
continue;
filePulls = filesData.get(fileName);
nodeName = pullNode.getText();
pullIdx = Integer.parseInt(nodeName.replaceAll(pullIndexReplaceString, "")) - 1;
pullData = filePulls.get(pullIdx);
if (pullData.size() == 0)
continue;
if (dirName == null) {
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory((lastPullExportDir == null ? fileChooser.getCurrentDirectory() : lastPullExportDir));
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fc.setAcceptAllFileFilterUsed(false);
if (JFileChooser.APPROVE_OPTION != fc.showSaveDialog(null))
return;
File dir = fc.getSelectedFile();
if (!dir.exists() || !dir.isDirectory()) {
JOptionPane.showMessageDialog(null, "Directory doesn't exist: " + dir.getAbsolutePath(), "Invalid directory", JOptionPane.ERROR_MESSAGE);
return;
}
lastPullExportDir = dir;
dirName = dir.getAbsolutePath();
}
ArrayList<String> columns = new ArrayList<String>();
ArrayList<ArrayList<Double>> data = new ArrayList<ArrayList<Double>>();
for (Map.Entry<String, ArrayList<Double>> entry : pullData.entrySet()) {
columns.add(entry.getKey());
data.add(entry.getValue());
}
Writer out = null;
try {
File file = new File(dirName + File.separator + fileName + "_" + nodeName + ".csv");
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, false), Config.getEncoding()));
int lidx = columns.size() - 1;
int rows = data.get(0).size();
for (i = 0; i <= lidx; ++i)
out.write(columns.get(i) + (i < lidx ? "," : ""));
out.write("\n");
for (j = 0; j < rows; ++j) {
for (i = 0; i <= lidx; ++i)
out.write(data.get(i).get(j) + (i < lidx ? "," : ""));
out.write("\n");
}
}
catch (Exception e) {
logger.error(e);
}
finally {
if (out != null) {
try {
out.close();
}
catch (IOException e) {
logger.error(e);
}
}
}
}
}
}
catch (Exception e) {
logger.error(e);
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
public void disposeLogView() {
logPlayButton.setEnabled(true);
logPlayWindow.dispose();
logPlayWindow = null;
startMarker = null;
endMarker = null;
disableMouseListener();
enableMouseListener();
chartPanel.repaint();
}
public void enableMouseListener() {
chartPanel.addChartMouseListener(chartMouseListener);
}
public void disableMouseListener() {
chartPanel.removeChartMouseListener(chartMouseListener);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == loadButton)
selectLogFile();
else if (e.getSource() == printButton)
logDataTable.print(new PrintProperties());
else if (e.getSource() == previewButton)
logDataTable.printPreview(new PrintProperties());
else if (e.getSource() == findButton) {
if (findWindow != null)
findWindow.dispose();
findWindow = new DBTFindFrame(SwingUtilities.windowForComponent(this), logDataTable, true);
}
else if (e.getSource() == replaceButton) {
if (findWindow != null)
findWindow.dispose();
findWindow = new DBTFindFrame(SwingUtilities.windowForComponent(this), logDataTable, false);
}
else if (e.getSource() == filterButton) {
String filterString = filterText.getText();
if (filterString != null && !"".equals(filterString) && !compareCombo.getSelectedItem().toString().isEmpty()) {
try {
CompareFilter filter = new CompareFilter();
filter.setCondition(CompareFilter.Condition.EQUAL);
if (compareCombo.getSelectedItem().toString().equals(greater))
filter.setCondition(CompareFilter.Condition.GREATER);
if (compareCombo.getSelectedItem().toString().equals(greaterEqual))
filter.setCondition(CompareFilter.Condition.GREATER_EQUAL);
else if (compareCombo.getSelectedItem().toString().equals(less))
filter.setCondition(CompareFilter.Condition.LESS);
else if (compareCombo.getSelectedItem().toString().equals(lessEqual))
filter.setCondition(CompareFilter.Condition.LESS_EQUAL);
filter.setFilter(filterText.getText());
filter.setColumn(logDataTable.getColumnByHeaderName((String)selectionCombo.getSelectedItem()).getModelIndex());
logDataTable.filter(filter);
updateChart();
}
catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(null, "Invalid numeric value: " + filterText.getText(), "Invalid value", JOptionPane.ERROR_MESSAGE);
}
}
else {
filterText.setText("");
compareCombo.setSelectedItem("");
logDataTable.filter(null);
updateChart();
}
}
else if (e.getSource() == viewButton) {
GridBagLayout gbl = (GridBagLayout)logViewPanel.getLayout();
if (viewButton.getText().startsWith("Headers")) {
Dimension d = viewButton.getSize();
viewButton.setMinimumSize(d);
viewButton.setPreferredSize(d);
viewButton.setMaximumSize(d);
gbl.rowWeights = new double[]{0.0, 1.0};
logDataTable.setVisible(false);
headerScrollPane.setVisible(true);
viewButton.setText("Grid View");
}
else {
gbl.rowWeights = new double[]{1.0, 0.0};
logDataTable.setVisible(true);
headerScrollPane.setVisible(false);
viewButton.setText("Headers View");
}
}
else if (e.getSource() == logPlayButton) {
if (logDataTable.getRowCount() > 1) {
if (logPlayWindow != null)
disposeLogView();
logPlayWindow = new LogPlay(this);
logPlayButton.setEnabled(false);
}
}
else if ("showpts".equals(e.getActionCommand())) {
showWotCurvePoints = ((JCheckBox)e.getSource()).isSelected();
for (int i = 0; i < wotPlot.getRendererCount(); ++i) {
XYLineAndShapeRenderer lineRenderer = (XYLineAndShapeRenderer)wotPlot.getRenderer(i);
XYSeriesCollection dataset = (XYSeriesCollection)wotPlot.getDataset(i);
if (lineRenderer == null || dataset == null)
continue;
for (int j = 0; j < dataset.getSeriesCount(); ++j)
lineRenderer.setSeriesShapesVisible(j, showWotCurvePoints);
}
}
else if ("export".equals(e.getActionCommand()))
exportSelectedWotPulls();
else if ("view".equals(e.getActionCommand()))
view3dPlots();
else if ("viewWot".equals(e.getActionCommand())) {
Enumeration<AbstractButton> buttons = wotRbGroup.getElements();
if (((JRadioButton)buttons.nextElement()).isSelected()) {
viewWotPlotsByRpm(false);
wotPlot.getDomainAxis(0).setLabel(rpmAxisName);
}
else if (((JRadioButton)buttons.nextElement()).isSelected()) {
viewWotPlotsByRpm(true);
wotPlot.getDomainAxis(0).setLabel(rpmAxisName);
}
else {
viewWotPlotsByTime();
wotPlot.getDomainAxis(0).setLabel(timeAxisName);
}
}
else if ("loadWot".equals(e.getActionCommand()))
selectWotLogFiles();
}
protected void onDroppedFiles(List<File> files) {
if (files.size() > 0) {
int idx = getSelectedIndex();
if (idx == 0) {
fileChooser.setMultiSelectionEnabled(false);
fileChooser.setCurrentDirectory(files.get(0));
fileChooser.setSelectedFile(files.get(0));
fileChooser.approveSelection();
loadLogFile();
}
else if (idx == 2) {
fileChooser.setMultiSelectionEnabled(true);
fileChooser.setCurrentDirectory(files.get(0));
fileChooser.setSelectedFiles((File[])files.toArray());
fileChooser.approveSelection();
loadWotLogFiles();
}
}
}
}